{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "### PyTorch nn 模块\n",
    "<p>nn模块主要负责构建神经网络的层(比如卷积层,池化层,全连接层等等)</p>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[8.1900],\n",
      "        [3.5700]])\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "import torch\n",
    "\n",
    "t_c =[0.5,14.0,15.0,28.0,11.0,8.0,3.0,-4.0,6.0,13.0,21.0] # 旧温度计\n",
    "t_u =[35.7,55.9,58.2,81.9,56.3,48.9,33.9,21.8,48.4,60.4,68.4] # 新温度计\n",
    "\n",
    "t_c = torch.tensor(t_c).unsqueeze(1)\n",
    "t_u = torch.tensor(t_u).unsqueeze(1)\n",
    "\n",
    "n_samples = t_u.shape[0]\n",
    "n_val = int(0.2*n_samples)\n",
    "shuffled_indices = torch.randperm(n_samples) # 打乱数据索引\n",
    "train_indices = shuffled_indices[:-n_val]\n",
    "val_indices = shuffled_indices[-n_val:]\n",
    "\n",
    "train_t_u = t_u[train_indices]\n",
    "train_t_c = t_c[train_indices]\n",
    "\n",
    "val_t_u = t_u[val_indices]\n",
    "val_t_c = t_c[val_indices]\n",
    "\n",
    "train_t_un = 0.1*train_t_u\n",
    "val_t_un = 0.1*val_t_u\n",
    "\n",
    "print(val_t_un)\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:12:22.661584200Z",
     "start_time": "2023-10-13T08:12:22.521578400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[3.7076],\n        [2.0571]], grad_fn=<AddmmBackward0>)"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linear_model = nn.Linear(1,1)# 包含3个参数:分别是输入张量的大小,输出张量的大小,默认为True的偏置\n",
    "linear_model(val_t_un)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:12:24.830037700Z",
     "start_time": "2023-10-13T08:12:24.445040400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "data": {
      "text/plain": "Parameter containing:\ntensor([[0.3573]], requires_grad=True)"
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linear_model.weight"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:17:41.401647100Z",
     "start_time": "2023-10-13T08:17:41.298637100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "data": {
      "text/plain": "Parameter containing:\ntensor([0.7817], requires_grad=True)"
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linear_model.bias"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:18:53.153538600Z",
     "start_time": "2023-10-13T08:18:53.134497Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([1.1389], grad_fn=<AddBackward0>)"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = torch.ones(1)\n",
    "linear_model(x)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:19:26.919601Z",
     "start_time": "2023-10-13T08:19:26.711577100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389],\n        [1.1389]], grad_fn=<AddmmBackward0>)"
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 输入一组批量为10的数据\n",
    "x = torch.ones(10,1)\n",
    "linear_model(x)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:25:12.605670200Z",
     "start_time": "2023-10-13T08:25:12.569673900Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 使用神经网络拟合温度计"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "torch.Size([11, 1])"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t_c =[0.5,14.0,15.0,28.0,11.0,8.0,3.0,-4.0,6.0,13.0,21.0] # 旧温度计\n",
    "t_u =[35.7,55.9,58.2,81.9,56.3,48.9,33.9,21.8,48.4,60.4,68.4] # 新温度计\n",
    "\n",
    "t_c = torch.tensor(t_c).unsqueeze(1)\n",
    "t_u = torch.tensor(t_u).unsqueeze(1)\n",
    "\n",
    "t_u.shape"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:29:05.807219700Z",
     "start_time": "2023-10-13T08:29:05.746189500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [],
   "source": [
    "from torch import optim\n",
    "linear_model = nn.Linear(1,1) # 构建线性函数\n",
    "optimizer = optim.SGD( # 优化器\n",
    "    linear_model.parameters(),\n",
    "    lr=1e-2\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:33:09.245159100Z",
     "start_time": "2023-10-13T08:33:09.222160200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "data": {
      "text/plain": "<generator object Module.parameters at 0x000001CA44D89A50>"
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linear_model.parameters() # 查看初始权重和偏置"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:33:25.479754800Z",
     "start_time": "2023-10-13T08:33:25.458753700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "data": {
      "text/plain": "[Parameter containing:\n tensor([[-0.8973]], requires_grad=True),\n Parameter containing:\n tensor([-0.3324], requires_grad=True)]"
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(linear_model.parameters())"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:34:06.664181600Z",
     "start_time": "2023-10-13T08:34:06.594212500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [],
   "source": [
    "def training_loop(n_epochs,optimizer,model,loss_fn,t_u_train,t_u_val,t_c_train,t_c_val):\n",
    "    for epoch in range(1,n_epochs+1):\n",
    "        t_p_train = model(t_u_train)\n",
    "        loss_train = loss_fn(t_p_train,t_c_train)\n",
    "\n",
    "        t_p_val = model(t_u_val)\n",
    "        loss_val = loss_fn(t_p_val,t_c_val)\n",
    "\n",
    "        optimizer.zero_grad()\n",
    "        loss_train.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        if epoch ==1 or epoch%1000 ==0:\n",
    "            print(f\"Epoch:{epoch}, Training loss: {loss_train.item() :.4f}\"\n",
    "                  f\"Validation loss:{loss_val.item() :.4f}\"\n",
    "                  )"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:49:03.889803900Z",
     "start_time": "2023-10-13T08:49:03.879814500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch:1, Training loss: 106.2064Validation loss:324.8937\n",
      "Epoch:1000, Training loss: 4.2414Validation loss:17.6012\n",
      "Epoch:2000, Training loss: 3.0086Validation loss:7.6928\n",
      "Epoch:3000, Training loss: 2.9183Validation loss:5.7079\n",
      "\n",
      "Parameter containing:\n",
      "tensor([[4.9291]], requires_grad=True)\n",
      "Parameter containing:\n",
      "tensor([-15.0779], requires_grad=True)\n"
     ]
    }
   ],
   "source": [
    "linear_model = nn.Linear(1,1)\n",
    "optimizer = optim.SGD(linear_model.parameters(),lr=0.01)\n",
    "training_loop(n_epochs=3000,\n",
    "              model=linear_model,\n",
    "              optimizer=optimizer,\n",
    "              loss_fn=nn.MSELoss(),\n",
    "              t_u_train=train_t_un,\n",
    "              t_u_val=val_t_un,\n",
    "              t_c_train=train_t_c,\n",
    "              t_c_val=val_t_c\n",
    "              )\n",
    "print()\n",
    "print(linear_model.weight)\n",
    "print(linear_model.bias)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:49:06.804803500Z",
     "start_time": "2023-10-13T08:49:05.492809Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 最终完成神经网络:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## nn提供了一种通过nn.sequential容器来连接模型的方式"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "data": {
      "text/plain": "Sequential(\n  (0): Linear(in_features=1, out_features=13, bias=True)\n  (1): Tanh()\n  (2): Linear(in_features=13, out_features=1, bias=True)\n)"
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seq_model = nn.Sequential(\n",
    "    nn.Linear(1,13),\n",
    "    nn.Tanh(),\n",
    "    nn.Linear(13,1)\n",
    ")\n",
    "seq_model"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:56:39.234944900Z",
     "start_time": "2023-10-13T08:56:39.211003100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.weight --- torch.Size([13, 1])\n",
      "0.bias --- torch.Size([13])\n",
      "2.weight --- torch.Size([1, 13])\n",
      "2.bias --- torch.Size([1])\n"
     ]
    }
   ],
   "source": [
    "for name,param in seq_model.named_parameters():\n",
    "    print(name,'---',param.shape)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T08:59:15.633005Z",
     "start_time": "2023-10-13T08:59:15.618012800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "data": {
      "text/plain": "Sequential(\n  (hidden_linear): Linear(in_features=1, out_features=13, bias=True)\n  (hidden_activation): Tanh()\n  (output_linear): Linear(in_features=13, out_features=1, bias=True)\n)"
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 为神经网络的每层参数命名\n",
    "from collections import OrderedDict\n",
    "\n",
    "seq_model = nn.Sequential(OrderedDict([\n",
    "    ('hidden_linear',nn.Linear(1,13)),\n",
    "    ('hidden_activation',nn.Tanh()),\n",
    "    ('output_linear',nn.Linear(13,1))\n",
    "]))\n",
    "seq_model"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T09:03:38.965409500Z",
     "start_time": "2023-10-13T09:03:38.939409700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "data": {
      "text/plain": "Parameter containing:\ntensor([-0.1018], requires_grad=True)"
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 访问其中的参数\n",
    "seq_model.output_linear.bias"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T09:04:38.890676300Z",
     "start_time": "2023-10-13T09:04:38.868678800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch:1, Training loss: 2.3854Validation loss:2.8888\n",
      "Epoch:1000, Training loss: 2.1282Validation loss:3.1144\n",
      "Epoch:2000, Training loss: 1.9976Validation loss:2.5155\n",
      "Epoch:3000, Training loss: 1.9193Validation loss:2.1983\n",
      "Epoch:4000, Training loss: 1.8743Validation loss:2.0587\n",
      "Epoch:5000, Training loss: 1.8462Validation loss:2.0385\n",
      "output tensor([[27.3580],\n",
      "        [ 2.4144]], grad_fn=<AddmmBackward0>)\n",
      "answer tensor([[28.0000],\n",
      "        [ 0.5000]])\n",
      "hidden tensor([[ 0.0022],\n",
      "        [-0.0102],\n",
      "        [-0.0096],\n",
      "        [-0.0122],\n",
      "        [-0.0120],\n",
      "        [-0.0015],\n",
      "        [-0.0096],\n",
      "        [ 0.0072],\n",
      "        [-0.0070],\n",
      "        [ 0.0016],\n",
      "        [-0.0216],\n",
      "        [-0.0035],\n",
      "        [ 0.0106]])\n"
     ]
    }
   ],
   "source": [
    "optimizer = optim.SGD(seq_model.parameters(),lr=0.001)\n",
    "\n",
    "training_loop(n_epochs=5000,\n",
    "              model=seq_model,\n",
    "              optimizer=optimizer,\n",
    "              loss_fn=nn.MSELoss(),\n",
    "              t_u_train=train_t_un,\n",
    "              t_u_val=val_t_un,\n",
    "              t_c_train=train_t_c,\n",
    "              t_c_val=val_t_c\n",
    "              )\n",
    "print('output',seq_model(val_t_un))\n",
    "print('answer',val_t_c)\n",
    "print('hidden',seq_model.hidden_linear.weight.grad)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-13T09:13:53.784454300Z",
     "start_time": "2023-10-13T09:13:50.689458900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
